package com.jsm.tf.net.protocol;

import com.alibaba.fastjson.JSON;
import com.jsm.tf.net.message.Message;
import com.jsm.tf.net.message.request.LoginMessage;
import com.jsm.tf.net.protocol.serialize.JDKSerializer;
import com.jsm.tf.net.protocol.serialize.Serializer;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.ByteToMessageCodec;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.Charset;
import java.util.List;

@Slf4j
public class MessageCodec extends ByteToMessageCodec<Message> {
    private Serializer serializer;

    public MessageCodec(Serializer serializer) {
        this.serializer = serializer;
    }

    public static void main(String[] args) throws Exception {
        final LoggingHandler LOGGING_HANDLER = new LoggingHandler();
        final MessageCodec MESSAGE_CODEC_SHARABLE = new MessageCodec(new JDKSerializer());
        EmbeddedChannel channel = new EmbeddedChannel(
                new LengthFieldBasedFrameDecoder(1024, 15, 4, 0, 0),
                LOGGING_HANDLER,
                MESSAGE_CODEC_SHARABLE);
        LoginMessage msg = new LoginMessage("jsm", "123456");

        //encode;
//        channel.writeOutbound(msg);
        //decode;
        ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer();
        new MessageCodec(new JDKSerializer()).encode(null, msg, buffer);
        channel.writeInbound(buffer);

    }

    @Override
    protected void encode(ChannelHandlerContext ctx, Message message, ByteBuf out) throws Exception {
        //魔数
        out.writeCharSequence(message.getMagic(), Charset.defaultCharset());   //5
        //版本号
        out.writeByte(message.getVersion()); //1
        //序列化算法
        out.writeByte(message.getSerializeType()); //1
        //指令
        out.writeByte(message.getCommandType()); //1
        //请求序号
        out.writeLong(message.getSeq());//8
        Serializer algorithm = Serializer.Algorithm.values()[message.getSerializeType()].getSerializer();
        byte[] data = algorithm.serialize(message);
        //内容长度
        out.writeInt(data.length); //4
        //内容字节数组
        out.writeBytes(data);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        CharSequence magic = in.readCharSequence(5, Charset.defaultCharset());
        byte version = in.readByte();
        byte serializeType = in.readByte();
        byte commandType = in.readByte();
        long seq = in.readLong();
        int length = in.readInt();
        byte[] data = new byte[length];
        in.readBytes(data, 0, length);
        Serializer algorithm = Serializer.Algorithm.values()[serializeType].getSerializer();
        Object message = algorithm.deserialize(Message.commandClassMap.get(commandType), data);
        out.add(message);
        log.info("magic:{},version:{},seq:{},length:{},message:{}", magic, version, seq, length, JSON.toJSONString(message));

    }
}
